package com.tianji.learning.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tianji.api.client.remark.RemarkClient;
import com.tianji.api.client.user.UserClient;
import com.tianji.api.dto.user.UserDTO;
import com.tianji.common.domain.dto.PageDTO;
import com.tianji.common.exceptions.BadRequestException;
import com.tianji.common.utils.BeanUtils;
import com.tianji.common.utils.CollUtils;
import com.tianji.learning.domain.dto.ReplyDTO;
import com.tianji.learning.domain.po.InteractionQuestion;
import com.tianji.learning.domain.po.InteractionReply;
import com.tianji.learning.domain.query.ReplyPageQuery;
import com.tianji.learning.domain.vo.ReplyVO;
import com.tianji.learning.enums.QuestionStatus;
import com.tianji.learning.mapper.InteractionQuestionMapper;
import com.tianji.learning.mapper.InteractionReplyMapper;
import com.tianji.learning.service.IInteractionReplyService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * <p>
 * 互动问题的回答或评论 服务实现类
 * </p>
 *
 * @author mytjxt
 * @since 2024-05-27
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class InteractionReplyServiceImpl extends ServiceImpl<InteractionReplyMapper, InteractionReply> implements IInteractionReplyService {
final InteractionQuestionMapper questionMapper;
final UserClient userClient;
final RemarkClient remarkClient;
    @Override
    @Transactional
    public void addReply(ReplyDTO replyDTO) {
       //1.新增reply
        InteractionReply reply = BeanUtils.copyBean(replyDTO, InteractionReply.class);
        reply.setUserId(replyDTO.getTargetUserId());
        save(reply);
        //查询关联的问题
        InteractionQuestion question = questionMapper.selectById(replyDTO.getQuestionId());
        //2.更新question的回复数量,更新question的评论数量
        if (replyDTO.getAnswerId() == null){//属于回答
            //2.1修改问题的最近一次回答
            if (question==null){
                throw new RuntimeException("问题不存在");
            }
            question.setLatestAnswerId(reply.getId());//自增主键回填
            //2.2累加问题表的回答次数
            question.setAnswerTimes(question.getAnswerTimes()+1);
            questionMapper.updateById(question);

        }  else {//属于评论
        //2.3累加该回答下的评论次数
            InteractionReply interactionReply = getById(replyDTO.getAnswerId());
            interactionReply.setReplyTimes(interactionReply.getReplyTimes()+1);
            updateById(interactionReply);
        }
        //判断是不是学生提交
        // 如果是学生提交，则需要更新问题状态为未查看
        if (replyDTO.getIsStudent()) {
            question.setStatus(QuestionStatus.UN_CHECK);
        }
        // 更新问题
        questionMapper.updateById(question);
        // TODO 尝试更新积分

    }

    @Override
    public PageDTO<ReplyVO> queryReplyPage(ReplyPageQuery query, boolean forAdmin) {
        // 1.问题id和回答id至少要有一个，先做参数判断
        Long questionId = query.getQuestionId();
        Long answerId = query.getAnswerId();
        if (questionId == null && answerId == null) {
            throw new BadRequestException("问题或回答id不能都为空");
        }
        // 标记当前是查询问题下的回答
        boolean isQueryAnswer = questionId != null;
        // 2.分页查询reply
        Page<InteractionReply> page = lambdaQuery()
                .eq(isQueryAnswer, InteractionReply::getQuestionId, questionId)
                .eq(InteractionReply::getAnswerId, isQueryAnswer ? 0L : answerId)
                .eq(!forAdmin, InteractionReply::getHidden, false)
                .page(query.toMpPage( // 先根据点赞数排序，点赞数相同，再按照创建时间排序
                        new OrderItem("liked_times", false),
                        new OrderItem("create_time", true))
                );
        List<InteractionReply> records = page.getRecords();
        if (CollUtils.isEmpty(records)) {
            return PageDTO.empty(page);
        }
        // 3.数据处理，需要查询：提问者信息、回复目标信息、当前用户是否点赞
        Set<Long> userIds = new HashSet<>();
        Set<Long> answerIds = new HashSet<>();
        Set<Long> targetReplyIds = new HashSet<>();
        // 3.1.获取提问者id 、回复的目标id、当前回答或评论id（统计点赞信息）
        for (InteractionReply r : records) {
            if(!r.getAnonymity() || forAdmin) {
                // 非匿名
                userIds.add(r.getUserId());
            }
            targetReplyIds.add(r.getTargetReplyId());
            answerIds.add(r.getId());
        }
        // 3.2.查询目标回复，如果目标回复不是匿名，则需要查询出目标回复的用户信息
        targetReplyIds.remove(0L);
        targetReplyIds.remove(null);
        if(targetReplyIds.size() > 0) {
            List<InteractionReply> targetReplies = listByIds(targetReplyIds);
            Set<Long> targetUserIds = targetReplies.stream()
                    .filter(Predicate.not(InteractionReply::getAnonymity).or(r -> forAdmin))
                    .map(InteractionReply::getUserId)
                    .collect(Collectors.toSet());
            userIds.addAll(targetUserIds);
        }
        // 3.3.查询用户
        Map<Long, UserDTO> userMap = new HashMap<>(userIds.size());
        if(userIds.size() > 0) {
            List<UserDTO> users = userClient.queryUserByIds(userIds);
            userMap = users.stream().collect(Collectors.toMap(UserDTO::getId, u -> u));
        }
        // 3.4.查询用户点赞状态
        Set<Long> bizLiked = remarkClient.isBizLiked(answerIds);
        // 4.处理VO
        List<ReplyVO> list = new ArrayList<>(records.size());
        for (InteractionReply r : records) {
            // 4.1.拷贝基础属性
            ReplyVO v = BeanUtils.toBean(r, ReplyVO.class);
            list.add(v);
            // 4.2.回复人信息
            if(!r.getAnonymity() || forAdmin){
                UserDTO userDTO = userMap.get(r.getUserId());
                if (userDTO != null) {
                    v.setUserIcon(userDTO.getIcon());
                    v.setUserName(userDTO.getName());
                    v.setUserType(userDTO.getType());
                }
            }
            // 4.3.如果存在评论的目标，则需要设置目标用户信息
            if(r.getTargetReplyId() != null){
                UserDTO targetUser = userMap.get(r.getTargetUserId());
                if (targetUser != null) {
                    v.setTargetUserName(targetUser.getName());
                }
            }
            // 4.4.点赞状态
            if (bizLiked!=null){
            v.setLiked(bizLiked.contains(r.getId()));
            }
        }
        return new PageDTO<>(page.getTotal(), page.getPages(), list);
    }


    /**
     * 管理端分页查询回答或评论列表
     * @param pageQuery 分页参数
     * @return  分页列表
     */
/*    @Override
    public PageDTO<ReplyVO> pageAdmin(ReplyPageQuery pageQuery) {
        // 校验问题id和回答id是否都为空
        if (pageQuery.getAnswerId() == null && pageQuery.getQuestionId() == null) {
            throw new BadRequestException("查询参数错误");
        }
        // 分页查询回答或评论列表
        Page<InteractionReply> replyPage = this.lambdaQuery()
                // 如果传问题id就把问题id作查询条件
                .eq(pageQuery.getQuestionId() != null, InteractionReply::getQuestionId, pageQuery.getQuestionId())
                .eq(InteractionReply::getAnswerId, pageQuery.getAnswerId() == null ? 0L : pageQuery.getAnswerId())     // 字段默认值0
                .page(pageQuery.toMpPage(new OrderItem("liked_times", false),
                        new OrderItem("create_time", true))); // 按照点赞次数降序排序降序，创建时间升序排序
        List<InteractionReply> records = replyPage.getRecords();
        if (CollUtil.isEmpty(records)) { // 查询不到，返回空集
            return PageDTO.of(replyPage, Collections.emptyList());
        }
        // 关联用户信息，先收集用户id，封装到map
        List<Long> userIds = new ArrayList<>();
        List<Long> targetUserIds = new ArrayList<>();   // 目标用户id
        List<Long> targetReplyIds = new ArrayList<>();   // 目标回复id???
        for (InteractionReply reply : records) {
            if (!reply.getAnonymity()) { // 非匿名用户需要查询
                userIds.add(reply.getUserId());
                // userIds.add(reply.getTargetUserId());
            }
            // "target_user_id"字段默认值为0，查询评论时生效
            if (reply.getTargetUserId() != null && reply.getTargetUserId() > 0) {
                targetUserIds.add(reply.getTargetUserId());
            }
            // "target_reply_id"字段默认值为0，查询评论时生效
            if (reply.getTargetReplyId() != null && reply.getTargetReplyId() > 0) {
                targetReplyIds.add(reply.getTargetReplyId());
            }
        }
        // 查询目标回复列表并封装为Map
        Map<Long, InteractionReply> targetReplyMap = new HashMap<>();
        // targetReplyIds不为空，去查询数据库
        if (!CollUtil.isEmpty(targetReplyIds)) {
            // 查询目标评论，并封装为Map
            List<InteractionReply> targetReplies = listByIds(targetReplyIds);
            targetReplyMap = targetReplies.stream().collect(Collectors.toMap(InteractionReply::getId, reply -> reply));

        }
        // 查询用户和目标回复用户并封装为Map
        Map<Long, UserDTO> userMap = new HashMap<>();
        if (!CollUtil.isEmpty(userIds)) {
            List<UserDTO> userDTOS = userClient.queryUserByIds(userIds);
            userMap = userDTOS.stream().collect(Collectors.toMap(UserDTO::getId, userDTO -> userDTO));
        }


        Map<Long, UserDTO> targetUserMap = new HashMap<>();
        if (!CollUtil.isEmpty(targetUserIds)) {
            List<UserDTO> targetUserDTOS = userClient.queryUserByIds(targetUserIds);
            targetUserMap = targetUserDTOS.stream().collect(Collectors.toMap(UserDTO::getId, userDTO -> userDTO));
        }

        // 保存结果
        List<ReplyVO> replyVOS = new ArrayList<>();
        for (InteractionReply reply : records) {
            ReplyVO replyVO = BeanUtil.toBean(reply, ReplyVO.class);
            UserDTO userDTO = userMap.getOrDefault(reply.getUserId(), null);
            // 如果当前回答或评论匿名，不进行赋值
            if (!replyVO.getAnonymity() && userDTO != null) {
                replyVO.setUserIcon(userDTO.getIcon()); // 回答人头像
                replyVO.setUserName(userDTO.getName()); // 回答人昵称
                replyVO.setUserType(userDTO.getType()); // 回答人类型
            }
            UserDTO targetUserDTO = targetUserMap.getOrDefault(reply.getTargetUserId(), null);
            InteractionReply targetReply = targetReplyMap.getOrDefault(reply.getTargetReplyId(), null);
            // 如果目标评论匿名，不进行赋值
            if (targetReply != null && !targetReply.getAnonymity() && targetUserDTO != null) {    // 目标回复非匿名才赋值
                replyVO.setTargetUserName(targetUserDTO.getName()); // 目标用户昵称
            }
            replyVOS.add(replyVO);
        }
        // 返回结果
        return PageDTO.of(replyPage, replyVOS);
    }*/










}
